import hashlib
import hmac
import json
import os
import platform
import requests
import time
from datetime import datetime, timedelta
from cryptography.fernet import Fernet
from PyQt6.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QMessageBox
from PyQt6.QtCore import Qt, QThread, pyqtSignal

class LicenseVerifier:
    def __init__(self):
        self.license_file = "license.dat"
        self.key_file = "license.key"
        self.server_url = "http://127.0.0.1:5000/api/license"  # 替换为您的后台地址
        self.secret_key = b"your-secret-key-here"  # 替换为您的密钥
        
        # 加载或生成加密密钥
        if os.path.exists(self.key_file):
            with open(self.key_file, 'rb') as f:
                key = f.read()
        else:
            key = Fernet.generate_key()
            with open(self.key_file, 'wb') as f:
                f.write(key)
        
        self.cipher_suite = Fernet(key)
        
    def get_machine_id(self):
        """获取机器唯一标识"""
        machine_info = f"{platform.node()}-{platform.machine()}-{platform.processor()}"
        return hashlib.sha256(machine_info.encode()).hexdigest()[:16]
    
    def verify_license_online(self, license_key):
        """在线验证license"""
        try:
            machine_id = self.get_machine_id()
            payload = {
                "license_key": license_key,
                "machine_id": machine_id,
                "timestamp": int(time.time())
            }
            
            # 创建签名
            signature = hmac.new(
                self.secret_key,
                json.dumps(payload, sort_keys=True).encode(),
                hashlib.sha256
            ).hexdigest()
            
            payload["signature"] = signature
            
            response = requests.post(
                self.server_url + "/verify",
                json=payload,
                timeout=10
            )
            
            if response.status_code == 200:
                result = response.json()
                if result.get("valid"):
                    # 保存license信息到本地
                    self.save_license_local(license_key, result)
                    return True, result.get("message", "License验证成功")
                else:
                    return False, result.get("message", "License无效")
            else:
                return False, "服务器验证失败"
                
        except requests.RequestException:
            # 网络错误时尝试本地验证
            return self.verify_license_offline(license_key)
        except Exception as e:
            return False, f"验证过程出错: {str(e)}"
    
    def verify_license_offline(self, license_key=None):
        """离线验证license（从本地缓存）"""
        try:
            if not os.path.exists(self.license_file):
                return False, "未找到本地license文件，需要联网验证"
            
            with open(self.license_file, 'rb') as f:
                encrypted_data = f.read()
            
            decrypted_data = self.cipher_suite.decrypt(encrypted_data)
            license_info = json.loads(decrypted_data.decode())
            
            # 如果提供了license_key，验证是否匹配
            if license_key and license_info.get("license_key") != license_key:
                return False, "License key不匹配"
            
            # 验证机器ID
            if license_info.get("machine_id") != self.get_machine_id():
                return False, "机器ID不匹配，license已绑定其他设备"
            
            # 验证过期时间
            expire_time = datetime.fromisoformat(license_info.get("expire_time"))
            if datetime.now() > expire_time:
                return False, "License已过期，请联系客服续费"
            
            # 计算剩余天数
            remaining_days = (expire_time - datetime.now()).days
            
            return True, f"License验证成功（离线模式），剩余{remaining_days}天"
            
        except Exception as e:
            return False, f"离线验证失败: {str(e)}"
    
    def save_license_local(self, license_key, server_response):
        """保存license信息到本地"""
        try:
            license_info = {
                "license_key": license_key,
                "machine_id": self.get_machine_id(),
                "expire_time": server_response.get("expire_time"),
                "user_info": server_response.get("user_info", {}),
                "last_verify": datetime.now().isoformat()
            }
            
            encrypted_data = self.cipher_suite.encrypt(
                json.dumps(license_info).encode()
            )
            
            with open(self.license_file, 'wb') as f:
                f.write(encrypted_data)
                
        except Exception as e:
            print(f"保存license失败: {e}")

class LicenseDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("软件激活")
        self.setFixedSize(400, 200)
        self.setWindowFlags(Qt.WindowType.Dialog | Qt.WindowType.WindowCloseButtonHint)
        self.license_verifier = LicenseVerifier()
        self.init_ui()
        
    def init_ui(self):
        layout = QVBoxLayout(self)
        
        # 标题
        title_label = QLabel("🔐 智能沟通机器人 - 软件激活")
        title_label.setStyleSheet("""
            QLabel {
                font-size: 16px;
                font-weight: bold;
                color: #2c3e50;
                padding: 10px;
            }
        """)
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(title_label)
        
        # License输入
        input_layout = QVBoxLayout()
        
        license_label = QLabel("请输入License Key:")
        license_label.setStyleSheet("font-weight: bold; margin-top: 10px;")
        input_layout.addWidget(license_label)
        
        self.license_input = QLineEdit()
        self.license_input.setPlaceholderText("请输入您购买的License Key")
        self.license_input.setStyleSheet("""
            QLineEdit {
                padding: 8px;
                border: 2px solid #bdc3c7;
                border-radius: 4px;
                font-size: 14px;
            }
            QLineEdit:focus {
                border-color: #3498db;
            }
        """)
        input_layout.addWidget(self.license_input)
        
        layout.addLayout(input_layout)
        
        # 按钮
        button_layout = QHBoxLayout()
        
        self.verify_button = QPushButton("激活")
        self.verify_button.setStyleSheet("""
            QPushButton {
                background-color: #3498db;
                color: white;
                border: none;
                padding: 10px 20px;
                border-radius: 4px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #2980b9;
            }
            QPushButton:pressed {
                background-color: #21618c;
            }
        """)
        self.verify_button.clicked.connect(self.verify_license)
        
        cancel_button = QPushButton("取消")
        cancel_button.setStyleSheet("""
            QPushButton {
                background-color: #95a5a6;
                color: white;
                border: none;
                padding: 10px 20px;
                border-radius: 4px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #7f8c8d;
            }
        """)
        cancel_button.clicked.connect(self.reject)
        
        button_layout.addWidget(self.verify_button)
        button_layout.addWidget(cancel_button)
        layout.addLayout(button_layout)
        
    def verify_license(self):
        license_key = self.license_input.text().strip()
        if not license_key:
            QMessageBox.warning(self, "警告", "请输入License Key")
            return
        
        self.verify_button.setText("验证中...")
        self.verify_button.setEnabled(False)
        
        # 验证license
        success, message = self.license_verifier.verify_license_online(license_key)
        
        self.verify_button.setText("激活")
        self.verify_button.setEnabled(True)
        
        if success:
            QMessageBox.information(self, "成功", message)
            self.accept()
        else:
            QMessageBox.critical(self, "激活失败", message)

def check_license():
    """检查license状态"""
    verifier = LicenseVerifier()

    # 首先尝试离线验证本地license
    if os.path.exists(verifier.license_file):
        try:
            with open(verifier.license_file, 'rb') as f:
                encrypted_data = f.read()
            
            decrypted_data = verifier.cipher_suite.decrypt(encrypted_data)
            license_info = json.loads(decrypted_data.decode())
            
            # 验证机器ID
            if license_info.get("machine_id") != verifier.get_machine_id():
                # 机器ID不匹配，需要重新激活
                return show_license_dialog()
            
            # 验证过期时间
            expire_time = datetime.fromisoformat(license_info.get("expire_time"))
            if datetime.now() > expire_time:
                # License已过期，需要重新激活
                return show_license_dialog()
            
            # 检查是否需要在线验证（每7天验证一次）
            last_verify = license_info.get("last_verify")
            if last_verify:
                last_verify_time = datetime.fromisoformat(last_verify)
                if datetime.now() - last_verify_time > timedelta(days=7):
                    # 尝试在线验证更新
                    license_key = license_info.get("license_key")
                    success, message = verifier.verify_license_online(license_key)
                    if not success:
                        # 在线验证失败，但本地license仍有效，继续使用
                        print(f"在线验证失败，使用本地license: {message}")
            
            # 本地license验证通过
            return True
            
        except Exception as e:
            print(f"本地license验证失败: {e}")
            # 本地license文件损坏，需要重新激活
            return show_license_dialog()
    
    # 没有本地license文件，需要激活
    return show_license_dialog()

def show_license_dialog():
    """显示license激活对话框"""
    from PyQt6.QtWidgets import QApplication
    app = QApplication.instance()
    if app is None:
        app = QApplication([])
    
    dialog = LicenseDialog()
    result = dialog.exec()
    
    return result == QDialog.DialogCode.Accepted

def get_license_info():
    """获取当前license信息"""
    verifier = LicenseVerifier()
    
    try:
        if not os.path.exists(verifier.license_file):
            return None, "未激活"
        
        with open(verifier.license_file, 'rb') as f:
            encrypted_data = f.read()
        
        decrypted_data = verifier.cipher_suite.decrypt(encrypted_data)
        license_info = json.loads(decrypted_data.decode())
        
        # 验证机器ID
        if license_info.get("machine_id") != verifier.get_machine_id():
            return None, "设备不匹配"
        
        # 获取过期时间
        expire_time = datetime.fromisoformat(license_info.get("expire_time"))
        
        if datetime.now() > expire_time:
            return expire_time, "已过期"
        
        # 计算剩余天数
        remaining_days = (expire_time - datetime.now()).days
        
        return expire_time, f"剩余{remaining_days}天"
        
    except Exception as e:
        return None, "读取失败"
